package com.nts.visionworks.business.application.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.nts.visionworks.business.application.domain.ApplicationMenu;
import com.nts.visionworks.business.application.domain.ApplicationSetting;
import com.nts.visionworks.business.application.domain.ApplicationSettingId;
import com.nts.visionworks.business.application.domain.ServiceApplication;
import com.nts.visionworks.business.application.domain.ServiceChannel;
import com.nts.visionworks.business.application.service.ApplicationService;
import com.nts.visionworks.business.contents.domain.Contents;
import com.nts.visionworks.business.endpoint.domain.EndPoint;

/**
 * 서비스 애플리케이션 관련 요청을 처리하기 위한 인터페이스를 제공한다.
 * @author Devcken
 */
@Controller
@RequestMapping("/application")
public class ApplicationController
{
	private final static Logger logger = LoggerFactory.getLogger(ApplicationController.class);
	
	/**
	 * 서비스 애플리케이션 관련 DAO를 주입받는다.
	 */
	@Resource(name="applicationService")
	private ApplicationService _applicationService;
	
	/**
	 * 서비스 애플리케이션 목록 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @return 조회된 서비스 애플리케이션 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/list", method=RequestMethod.GET)
	public ModelAndView listServiceApplications(HttpServletRequest request)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<ServiceApplication> serviceApplications = this._applicationService.listServiceApplications();
			
			map.put("serviceApplications", serviceApplications);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션 정보 저장 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param serviceApplication 저장하려는 서비스 애플리케이션 정보가 전달된다.
	 * @return 저장된 서비스 애플리케이션 정보를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/save", method=RequestMethod.GET)
	public ModelAndView saveServiceApplication(HttpServletRequest request,
			ServiceApplication serviceApplication)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			this._applicationService.saveServiceApplication(serviceApplication);
			
			map.put("serviceApplication", serviceApplication);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션 사용 불가 처리 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 사용 불가 처리할 서비스 애플리케이션의 아이디가 전달된다.
	 * @return 사용 불가 처리 성공 여부를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/disable", method=RequestMethod.GET)
	public ModelAndView disableServiceApplication(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			boolean result = this._applicationService.diableServiceApplication(applicationId);
			
			map.put("result", result);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션 환경 설정 목록 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 조회하려는 환경 설정의 서비스 애플리케이션 아이디가 전달된다.
	 * @return 서비스 애플리케이션 환경 설정 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/setting/list", method=RequestMethod.GET)
	public ModelAndView listServiceApplicationSettings(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<ApplicationSetting> serviceApplicationSettings = this._applicationService.listServiceApplicationSettings(applicationId);
			
			map.put("serviceApplicationSettings", serviceApplicationSettings);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션 환경 설정 저장 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param serviceApplicationSetting 저장하려는 서비스 애플리케이션 환경 설정 정보가 전달된다.
	 * @return 저장된 서비스 애플리케이션 환경 설정 정보를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/setting/save", method=RequestMethod.GET)
	public ModelAndView saveServiceApplicationSetting(HttpServletRequest request,
			ApplicationSetting serviceApplicationSetting,
			@RequestParam(value="settingId", required=false, defaultValue="0")Integer settingId,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			serviceApplicationSetting.setId(new ApplicationSettingId(settingId, applicationId));
			
			this._applicationService.saveServiceApplicationSetting(serviceApplicationSetting);
			
			map.put("serviceApplicationSetting", serviceApplicationSetting);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션 환경 설정 삭제 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param settingId 삭제하려는 서비스 애플리케이션 환경 설정 아이디가 전달된다.
	 * @param applicationId 삭제하려는 서비스 애플리케이션 환경 설정의 애플리케이션 아이디가 전달된다.
	 * @return 서비스 애플리케이션 환경 설정 삭제 여부를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/setting/delete", method=RequestMethod.GET)
	public ModelAndView deleteServiceApplicationSetting(HttpServletRequest request,
			@RequestParam(value="settingId", required=true)Integer settingId,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			boolean result = this._applicationService.deleteServiceApplicationSetting(settingId, applicationId);
			
			map.put("result", result);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 애플리케이션에 속하는 끝점 목록 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 서비스 애플리케이션 아이디가 전달된다.
	 * @return 서비스 애플리케이션 끝점 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/endpoints", method=RequestMethod.GET)
	public ModelAndView listServiceApplicationEndPoints(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<EndPoint> serviceApplicationEndPoints = this._applicationService.listServiceApplicationEndPoints(applicationId);
			
			map.put("serviceApplicationEndPoints", serviceApplicationEndPoints);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 채널 목록 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 서비스 애플리케이션 아이디가 전달된다.
	 * @return 서비스 채널 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/channel/list", method=RequestMethod.GET)
	public ModelAndView listServiceChannel(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<ServiceChannel> serviceChannels = this._applicationService.listServiceChannels(applicationId);
			
			map.put("serviceChannels", serviceChannels);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 서비스 채널 저장 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param serviceChannel 저장하려는 서비스 채널 정보가 전달된다.
	 * @return 저장된 서비스 채널 정보를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/channel/save", method=RequestMethod.GET)
	public ModelAndView saveServiceChannel(HttpServletRequest request,
			ServiceChannel serviceChannel,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			this._applicationService.saveServiceChannel(serviceChannel, applicationId);
			
			map.put("serviceChannel", serviceChannel);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 애플리케이션 메뉴 목록 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 조회하려는 애플리케이션 메뉴에 대한 애플리케이션 아이디가 전달된다.
	 * @return 조회된 애플리케이션 메뉴 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/menu/list", method=RequestMethod.GET)
	public ModelAndView listApplicationMenu(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<ApplicationMenu> applicationMenus = this._applicationService.listApplicationMenus(applicationId);
			
			map.put("applicationMenus", applicationMenus);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 애플리케이션 메뉴 저장 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param applicationId 저장하려는 애플리케이션 메뉴에 대한 애플리케이션 아이디가 전달된다.
	 * @param applicationMenu 저장하려는 애플리케이션 메뉴 정보가 전달된다.
	 * @return 저장된 애플리케이션 메뉴를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/menu/save", method=RequestMethod.GET)
	public ModelAndView saveApplicationMenu(HttpServletRequest request,
			@RequestParam(value="applicationId", required=true)Integer applicationId,
			ApplicationMenu applicationMenu)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			this._applicationService.saveApplicationMenu(applicationId, applicationMenu);
			
			map.put("applicationMenu", applicationMenu);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 애플리케이션 메뉴 사용 여부 변경 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param menuId 사용 여부를 변경하려는 애플리케이션 메뉴의 아이디가 전달된다.
	 * @param usable 변경하려는 사용 여부가 전달된다.
	 * @return 사용 불가 처리 성공 여부를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/menu/usable", method=RequestMethod.GET)
	public ModelAndView updateApplicationMenuUsable(HttpServletRequest request,
			@RequestParam(value="menuId", required=true)Long menuId,
			@RequestParam(value="usable", required=true)Boolean usable)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			boolean result = this._applicationService.updateApplicationMenuUsable(menuId, usable);
			
			map.put("result", result);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 애플리케이션 메뉴 삭제 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param menuId 삭제하려는 애플리케이션 메뉴 아이디가 전달된다.
	 * @return 애플리케이션 메뉴 삭제 여부를 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/menu/delete", method=RequestMethod.GET)
	public ModelAndView deleteApplicationMenu(HttpServletRequest request,
			@RequestParam(value="menuId", required=true)Long menuId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			boolean result = this._applicationService.deleteApplicationMenu(menuId);
			
			map.put("result", result);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
	
	/**
	 * 애플리케이션 메뉴 컨텐츠 목록 조회 요청에 대한 처리 결과를 뷰로 전달한다.
	 * @param request HTTP 서블릿에 대한 요청 정보가 전달된다.
	 * @param menuId 조회하려는 컨텐츠에 대한 애플리케이션 메뉴 아이디가 전달된다.
	 * @return 조회된 애플리케이션 메뉴 컨텐츠 목록을 포함하는 {@link org.springframework.web.servlet.ModelAndView.ModelAndView} 개체를 반환한다.
	 */
	@RequestMapping(value="/menu/contents", method=RequestMethod.GET)
	public ModelAndView listApplicationMenuContents(HttpServletRequest request,
			@RequestParam(value="menuId", required=true)Long menuId)
	{
		Map<String, Object> map = new HashMap<String, Object>();
		
		try
		{
			List<Contents> applicationMenuContents = this._applicationService.listApplicationMenuContents(menuId);
			
			map.put("applicationMenuContents", applicationMenuContents);
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return new ModelAndView("jsonView", map);
	}
}